Repository navigation
Conversation
|
Closing to trim scope; will reopen a smaller version. |
c81642e to
cdbfe44
Compare
Claude Code can switch models mid-conversation: when the safety classifiers refuse a request on Fable 5, the CLI re-runs it on Opus. OpenCode kept showing the requested model, so the user never knew. Surface the real model as a short callout after the answer: - model switched: system/model_refusal_fallback (models, category, scope) - model refused: model_refusal_no_fallback, turn ended with an error - model mismatch: init.model or assistant.message.model differs from the user's pick (catches switches the CLI does not announce) One note per leg, after the text so it cannot land inside a code fence. OPENCODE_CLAUDE_MODEL_NOTES=reasoning moves it to the thinking trace. system/notification events (medium+) go to the reasoning trace as [notice].
cdbfe44 to
69a7ab4
Compare
…l calls in parallel The SDK streams one assistant event per completed content block, so a turn with N parallel tool_use requests arrives as N separate events sharing a message id, all before the SDK invokes any tool handler. Handlers are then invoked serially, awaiting handler #1's return before starting openchamber#2. The bridge only ever knew about a tool once its handler ran, so a park always carried just the one tool the SDK had gotten around to calling — every later handler in the batch waited its turn. Register each tool_use block as it streams past, before any handler runs, keyed by Claude's own id with a deferred result promise. The first handler to park now emits the whole batch; handlers invoked later just look up their already-registered promise instead of re-parking one at a time.
|
Thanks, this was a great catch and sorry it sat so long. 1.2.2 handles it in a smaller way: when Claude Code falls back to another model after a refusal, there's a note in the reasoning and the OpenCode session switches to the model that's actually answering. Closing, thank you! |
|
Thanks for addressing this! Could we reopen this PR to discuss two remaining points?
Knowing which model answered and choosing which model handles the next message are separate things. That's the distinction I'd like to preserve. |
Claude Code can switch models mid-conversation: when the safety classifiers refuse a request on Fable 5, the CLI silently re-runs it on Opus. OpenCode keeps displaying the model the user picked, so there is no way to tell.
This adds a short callout at the end of the answer whenever the answering model differs from the selected one:
model switched- from the SDKmodel_refusal_fallbackevent (models, safeguard category, scope).model refused-model_refusal_no_fallback: the turn ended with an error and no retry ran.model mismatch(answer starts on X) -init.modeldiffers from the user's pick: the session was left on a fallback model by an earlier turn.model mismatch(answered by X) -assistant.message.modeldiffers from what was announced: catches switches the CLI doesn't report.One note per leg, always after the text so it can't land inside a code fence.
OPENCODE_CLAUDE_MODEL_NOTES=reasoningmoves it into the thinking trace instead. CLIsystem/notificationevents (medium+) are forwarded to the reasoning trace as[notice].Seen live with CLI 2.1.237: bio -> claude-opus-5, cyber -> claude-opus-4-8.